"""
此版本支持登陆自己的账号,无需手动更改cookies
"""
import json
import os
import requests
from bs4 import BeautifulSoup
from tqdm import tqdm
import asyncio
import aiofiles  # 异步操作文件

# 定义全局cookies
cookies_All = None


# json解析函数
def parse_json_with_error_handling(json_str):
    try:
        # 尝试解析 JSON 字符串
        parsed_json = json.loads(json_str)
        return parsed_json
    except json.JSONDecodeError as e:
        # 获取错误信息
        error_message = str(e)
        # print(f"JSON 解析错误(不用管): {error_message}\n")
        print(f"JSON 努力解析中...\n")
        # 找到错误位置
        error_pos = e.pos
        # 尝试截断字符串并重新解析
        truncated_json = json_str[:error_pos]
        try:
            parsed_json = json.loads(truncated_json)
            return parsed_json
        except json.JSONDecodeError:
            print("即使截断后也无法解析 JSON 字符串")
            return None


# 定义获取cookie函数    内含登录与验证码验证操作
def loginPddGetCookies():
    yourPhone = input("请输入手机号: ")
    # URL
    url = 'https://mobile.yangkeduo.com/proxy/api/api/sigerus/mobile/code/request'

    # 参数
    params = {
        'pdduid': 0,
    }

    # 请求体 - 如果是JSON格式
    json_data = {
        "platform": "4",
        "fingerprint": "{\"innerHeight\":1229,\"innerWidth\":2496,\"devicePixelRatio\":0.75,\"availHeight\":1032,\"availWidth\":1920,\"height\":1080,\"width\":1920,\"colorDepth\":24,\"locationHerf\":\"https://mobile.yangkeduo.com/login.html?from=https%3A%2F%2Fmobile.yangkeduo.com%2Fpjlkvgcf.html%3F_live_share_token%3DCRQ46EEGIEMXATU2NPB2SDCKSN3FIZZTCITIONO7ZRLOQH5CWIWKP4JAI64MZJ3GI2SYHRBQQULEM7UK32D2T6E5NKY6GMUWLFIZ6UQJRRAL5LPF45XVKHN4INYVOQIA%26refer_share_channel%3Dcopy_link%26mall_id%3D649584606%26page_from%3D601129%26refer_share_id%3DG3OiO3IWXbeIHPDNbB2HtJwO72WRlQU0%26refer_share_uin%3DUYSGSN6OZYI3ZCQRREZTO3FW4Y_GEXDA%26_x_share_id%3DG3OiO3IWXbeIHPDNbB2HtJwO72WRlQU0%26refer_page_name%3Dlogin%26refer_page_id%3D10169_1722933421511_zeph4lzajg%26refer_page_sn%3D10169&_x_share_id=G3OiO3IWXbeIHPDNbB2HtJwO72WRlQU0&refer_page_name=yhzb_bfy&refer_page_id=31430_1722934355555_3gz7a8wwcm&refer_page_sn=31430\",\"referer\":\"yhzb_bfy\",\"timezoneOffset\":-480,\"navigator\":{\"appCodeName\":\"Mozilla\",\"appName\":\"Netscape\",\"hardwareConcurrency\":8,\"language\":\"zh-CN\",\"cookieEnabled\":true,\"platform\":\"Win32\",\"doNotTrack\":null,\"ua\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36\",\"vendor\":\"Google Inc.\",\"product\":\"Gecko\",\"productSub\":\"20030107\"}}",
        "touchevent": "{}",
        "mobile": yourPhone,
        "screen_token": "0asAfxcydiKyj9maQBRvgBfP-3zpqlZ-TjmMYpiLxxhxobeJD1ye5_DV3t8keO8U3eMu_yKswv8BSCTs_NrtwXNLBsXmGEp25hn4dbSY0SgL5xX2ZIPL04GZZqvoQ4spiboF2mPMgYM-au7b4-aLDFspFK1cZyxKII_lnim87uSjRyeqiLFftKXfrGtsoYfUB0BEoKBY3-Sczr4gRE7z5U4QLsjHAUVuzVGkxjAVBbNOAao54TgpoJYo51mCRbDNwJNgtKkN_yN4_ykmT8ACnbybS7K_qllTjAI0pCBJzYg4SpQZtoauj4czFqobkiCzAOto9g8inD23u18vNgcokU91nb-dn7r04Y17T2joWQCw8J6Fkr9pN6bHPgACrcBACwM50TnsKay2pro1XQDnHWYGxLi8cWFHE4OIOIsgJkrP4dbSHzvB0BpejX5FZy147eAqS4ZGkOtUtMyPCFuRMEHJMvj2GpjoxBn3wqWG8k_k7JlZCWZQsuFbbdOKr2xvmIYKVdUTUw6SzLUQi5cnNzDBtzYmM2OpL5eCWKaHxWjbFbWLoX3Wz8ExR6abdL7jbJ37B_-jF-oVK3bM2f7thqhGbiALf7t6XNYu1mnwv1ZSfZ_YVAT4PvCI9jcwYwalihwdDAYsAM_eeLnOEFa1i1uhXABh3BzmP5IrpMlNsqAwEfOXZRjPFwzRyYz55FNnSprTObqkdDVUKrbd3-UYqKcc4qXy5G-1vgqfN1y5IDZA6ioCCKHwktQiB2x3R2a34PjXQer1bOKN_5ny4bIfxGxXfJlt8m6qMsd_1tyOy_Tf2AElgwaTLV7E2P3kHCDq3qMX9mkLX1yugq4t70c8PuY-hMpB_DTFRN5vlJhZdd4efkX4EIUB9xj0ao-PgsMKjMhqXT_aigTK3wZpfg1w8wMX2KCVNVsyYfECL2W5O-SiadPkzCU"
    }

    # 或者如果你的数据不是JSON格式
    # data = {
    #     'field1': 'value3',
    #     'field2': 'value4'
    # }

    # 发送请求
    loginFlag = input("是否发送验证码?1发送,0不发送。请输入:")
    if (loginFlag == '1'):
        response = requests.post(url, params=params, json=json_data)
        # 检查响应状态码
        if response.status_code == 200:
            # 成功获取响应
            print("Success!已发送验证码!")
            # print(response.json())  # 假设响应是JSON格式
            # 响应成功之后  输入验证码登录请求
            # yourCode = '394122'
            yourCode = input("请输入验证码: ")
            # print(f"您输入的内容是: {yourCode}")
            # URL
            url_code = 'https://mobile.yangkeduo.com/proxy/api/api/sigerus/login_mobile'

            # 参数
            params_code = {
                'pdduid': 0,
            }
            json_code = {
                "mobile": yourPhone,
                "code": yourCode,
                "anti_content": "0asWtqly7ifs8suaTPcQdML5bUWpG9FVFqBJQL8JDDk1trYg3chLKFJJbYmo68JJki3QNymBstffMP8p5GzJoZ0I02KNJNGwFfB_vk4tBsv4fsk6_kZT_1_SX8f3bsoCtrSiRXZ2zDX4E-rD2Qm4Qu7ywQkHKVOLO7_X-jE-k7NQCwjnS2BcuqVP32x8BoKARwMr2wLMPnTAVaAqEF6hbpT3IYQK-ZvzE_Wz2_c0_9nWCnJXQXmqlAkjXG2Cyp63-gXTXL6UQ98nEfPAVIC_hrgJODofpiVmR2Uq2mO4gLsStiPXWlbTYfnWxSC2cAZXRgoagtOP9bpTfPAx-m4RJSd2r3ZgNsTn83ZGRg5VVM9encVJfqm84GenWlSm4sN8fOXen8nSq0hrNv3nPgEZ4oel4UA53lVxKxPASdA9BBPRaG3tmJ7ZGLSnqCOA-Ml5ttVnJV-SZfLh-_mztEcFZKEBzc0-Lzdnv8zqJuo3YOHNxyjuTiH4PfLGD7LbiPer-qROqeO5Aj0QtTVlp6OIq-4qEA7nNjlXHCE7jooce_YWD85i8g9oHKNIHpvJBFyrD_XDGIyMTfbPGzQcNAlQ7ZJOPWxV-OLc19ZgAPf7fuJWNbyIB-_FSVrmpQtaUk_Lz4TkbZ6-I4f6j-6wP0rqKVWcLhfIsqStDBl5TZsJvbrTdDSMqUyjmsl9hQstGesK-Df1cw5VFS2ka18qh6xFdhXDQBUo0mRPoB8xTRui_kqDmMPprn-P4-nGMFhqmBZkJlgZTz1JvaVLGP0H-4SbjM8cC9EdkKxttXUQk1lGFYexNzp7FcHjFWIypgSn1ZVvGakGoUT9rZLM4Pmq_GkUqdkYSKIEOzpgHGMn-3WTVsMHkuGiov9SdKk39JkxKweDVajnwDUkb8OEZEKlB5iIFFXAPOdwumCXOu0SCEzJSk9qGVGcOcDf0IM9EzGrtP-hCvz2gN4sWZSZVvfD7V9",
                "add_cookie": True,
                "login_app_id": 155
            }
            # 发送请求
            response = requests.post(url_code, params=params_code, json=json_code)

            # 检查响应状态码
            if response.status_code == 200:
                # 成功获取响应
                print("Success!已成功登录!")
                # print('全部cookie', response.cookies)
                # print("响应内容",response.cookies)
                for cookie in response.cookies:
                    if cookie.name == 'PDDAccessToken':
                        # print('真实PDDAccessToken',cookie.value)
                        return cookie.value
        else:
            print(f"登录失败,请联系管理员!")
    else:
        print("取消发送;若要再次发送,请重新打开程序!")
        raise ValueError("您已取消发送,为防止频繁发送验证码,若要再次发送,请重新打开程序!!")


# 清除txt文件全部内容
def clear_txt_file_cookies():
    with open('cookies.txt', 'w') as file:
        file.truncate(0)


# 从本地获取token
def getCkFromTxt():
    # 从 txt 文件中取出 cookies 并使用
    try:
        with open('cookies.txt', 'r', encoding='utf-8') as f:
            return f.read()
    except EOFError:
        # 处理文件为空的情况
        return False


# 判断本地是否有token
def judgeHasCk():
    # 从 txt 文件中取出 cookies 并使用
    try:
        with open('cookies.txt', 'r', encoding='utf-8') as f:
            cookies_has = f.read()
            if cookies_has != '':
                return True
            else:
                return False
    except EOFError:
        # 处理文件为空的情况
        return False


# 根据直播地址和cookies获取直播视频  异步函数
async def downVideoByUrl(url):
    # 先从本地获取cookie
    global cookies_All
    # cookies_All = loginPddGetCookies()
    if judgeHasCk():
        print("登录信息已经保存,无需登录.")
        cookies_All = getCkFromTxt()
        # print("本地获取cookie成功,无需登录.")
    else:
        print("没有登录信息,请登录.")
        # 本地没有,则登录获取cookie
        cookies_All = loginPddGetCookies()
        # 将 cookies 存入 txt 文件
        with open('cookies.txt', 'w', encoding='utf-8') as f:
            f.write(cookies_All)
            print("登录信息已经保存.")

    # 添加 cookies
    cookies_value = cookies_All
    # print(cookies_value)
    # cookies = {
    #     'PDDAccessToken': cookies_value
    # }
    cookies = {
        'PDDAccessToken': cookies_value
        # 'PDDAccessToken':'Z7GWKTNRUMKHMLBHE3M2BZKAUIB4DLNVGOW65R74JHSBVR2XK4CQ12022a1'
    }
    #     {
    #     # 成功跳过验证   但是肯定有时间  还得重新登录   收到个短信?
    #     'PDDAccessToken': 'H2ABJ6UB6QVIPXA4O6FO4RDZPGL5Y54WGNKBCGDPAUNSRVVJJEQA12022a1',
    #     # 更多 cookies...
    # }

    # 发送带有 cookies 的请求并获取响应
    response = requests.get(url, cookies=cookies)

    # 需要下来的视频流地址
    needDown = ''
    # 直播间名称
    homeName = ''
    # 买的东西
    showName = ''

    # 检查请求是否成功
    if response.status_code == 200:
        # 解析HTML
        soup = BeautifulSoup(response.text, 'html.parser')

        # 查找所有的 <script> 标签
        script_tags = soup.find_all('script')
        # print('main', script_tags)

        # 输出每个 <script> 标签的内容
        for script in script_tags:
            # 输出 <script> 标签的文本内容
            script_content = script.string
            if script_content is None:
                # 如果没有直接的 string 属性，尝试获取所有文本
                script_content = script.get_text()
            if "window.rawData" in script_content:
                objStr = script_content.replace(' window.rawData=', '')
                objStr = objStr.strip()
                # print(objStr)
                if "null;" == objStr:
                    print("登录失效,请重新登录!")
                    clear_txt_file_cookies()  # 清除本地的cookies   以达到重新登录的效果
                    raise ValueError("尚未登录,请重新登录! 或者检查直播是否开播!")
                else:
                    # 去转义
                    objJson = parse_json_with_error_handling(objStr)
                    # 直播间名称
                    homeName = objJson['store']['shareInfo']['pinxiaoquanShareTitle']
                    # 所有视频地址
                    playUrlList = objJson['store']['playUrlList']
                    for index, item in enumerate(playUrlList):
                        if index == 0:
                            # 获取第一个视频地址
                            playUrl = item['playUrl']
                            # 下载第一个
                            needDown = playUrl
                    if homeName == '' or homeName is None:
                        print('此直播间已经关播')
                        raise ValueError("此直播间已经关播,请更换直播源!若更换直播源后仍为此错误,可能是此号登录频繁,请手动将此号登陆至电脑端观察是否能查看直播;若手动登录也不能看,"
                                         "请更换账户登录!!!")
                    else:
                        print(homeName + 'start...')

                    # 设置输出文件地址
                    folder_path = homeName
                    # 检查文件夹是否存在
                    if not os.path.exists(folder_path):
                        # 如果不存在，则创建文件夹
                        os.makedirs(folder_path)
                        print(f"文件夹 '{folder_path}' 创建成功。")
                    else:
                        print(f"文件夹 '{folder_path}' 已存在。")
                    output_filename = folder_path + '/' + homeName + '.mp4'

                    # 发送请求并获取响应
                    response = requests.get(needDown, stream=True)

                    # 获取文件大小
                    total_size_in_bytes = int(response.headers.get('content-length', 0))

                    # 检查请求是否成功
                    if response.status_code == 200:
                        # 使用tqdm创建一个进度条
                        progress_bar = tqdm(desc='正在获取' + homeName + '的内容',
                                            total=total_size_in_bytes,
                                            unit='iB',
                                            unit_scale=True,
                                            mininterval=1)

                        # 以二进制模式打开文件，并写入数据
                        async with aiofiles.open(output_filename, 'wb') as f:
                            for data in response.iter_content(chunk_size=1024):
                                size = await f.write(data)  # 异步等待
                                progress_bar.update(size)

                        # 关闭进度条
                        progress_bar.close()

                        print(f"视频已成功下载为 {output_filename}")
                    else:
                        print("下载失败，状态码:", response.status_code)

    else:
        print("请求失败，状态码:", response.status_code)


# 读取txt文件内容 批量处理函数
async def main():
    # 打开文件并读取每一行
    with open('pddAdr.txt', 'r', encoding='utf-8') as file:
        urls = file.readlines()
    await asyncio.gather(*[downVideoByUrl(url) for url in urls])


# 运行异步程序   程序入口
asyncio.run(main())
